/**
 * 
 *  JavaScript holding the OpenStreetMap functionality.
 *   
 */


var DEFAULT_CENTER_LON = 21.2502;
var DEFAULT_CENTER_LAT = 48.7170;
var DEFAULT_ZOOM = 1;
var CROSSHAIR_IMG_ADDRESS = 'http://' + window.location.host + '/resources/target_icon.png';
var CROSSHAIR_IMG_RADIUS = 15;
var CENTER_MAP_INTERVAL = 60000;

var map;
var crosshairControl;

/**
 * Initializes the OpenStreetMap component
 *
 * @param {Object} center_lon the longitude part of the center location
 * @param {Object} center_lat the latitude part of the center location
 * @param {Object} zoom the zoom level
 * @param {Object} div_id ID of the HTML div element, which will be the map component
 *
 * @author molnala
 */
function initOSM(center_lon, center_lat, zoom, div_id){
    // check the arguments
    var center_lon = (center_lon != undefined) ? center_lon : DEFAULT_CENTER_LON;
    var center_lat = (center_lat != undefined) ? center_lat : DEFAULT_CENTER_LAT;
    var zoom = (zoom != undefined) ? zoom : DEFAULT_ZOOM;
    
    if (div_id == undefined) 
        return; // TODO at least an error log!
        
    var mapInitTextElem = document.getElementById('mapInitText');
    if (mapInitTextElem) {
        document.getElementById(div_id).removeChild(mapInitTextElem);    
    }
    
    OpenLayers.Control.PanZoom.prototype.draw = function(px){
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        px = this.position;
        this.buttons = [];
        var sz = new OpenLayers.Size(28, 28);
        var centered = new OpenLayers.Pixel(px.x + sz.w / 2, px.y);
        this._addButton("panup", "north-mini.png", centered, sz);
        px.y = centered.y + sz.h;
        this._addButton("panleft", "west-mini.png", px, sz);
        this._addButton("panright", "east-mini.png", px.add(sz.w, 0), sz);
        this._addButton("pandown", "south-mini.png", centered.add(0, sz.h * 2), sz);
        this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h * 3 + 5), sz);
        this._addButton("zoomworld", "zoom-world-mini.png", centered.add(0, sz.h * 4 + 5), sz);
        this._addButton("zoomout", "zoom-minus-mini.png", centered.add(0, sz.h * 5 + 5), sz);
        return this.div;
    };
    
     map = new OpenLayers.Map(div_id, {
        controls: [
            new OpenLayers.Control.Navigation(),        // navigation controls
            new OpenLayers.Control.PanZoom(),        // zooming controls
            new OpenLayers.Control.LayerSwitcher(),     // layer switcher controls
            new OpenLayers.Control.MousePosition()],    // show the mouse position (lon, lat)
     //   maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
      //  maxResolution: 156543.0399,
       // units: 'm',
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG:4326")
    });

    // add the renderer layer
    layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
    map.addLayer(layerMapnik);

    // set the center position and zoom level
    var lonLat = new OpenLayers.LonLat(center_lon, center_lat).transform(map.displayProjection, map.getProjectionObject());
    map.setCenter(lonLat, zoom);
    
    // create and add the layer showing the friends
    var layerFriends = new OpenLayers.Layer.SituareFriends("Friends");
    map.addLayer(layerFriends);
    
    // create and add the crosshair control
    crosshairControl = new OpenLayers.Control.SituareCrosshair();
    map.addControl(crosshairControl);
//    map.baseLayer.redraw();
//    crosshairControl.draw();
    
    map.events.register("moveend", map, moveendEvent);
//    crosshairControl.events.register("resize", map, updateCrosshair); 
    
    setInterval(setMapToCenter,CENTER_MAP_INTERVAL);

    return layerFriends;    
}

function setMapToCenter() {
    if (map) {
	    var zoom = undefined; 
	    var center_lon = document.getElementById("input_lon").value;
	    var center_lat = document.getElementById("input_lat").value;
	    // set the center position and zoom level
	    var lonLat = new OpenLayers.LonLat(center_lon, center_lat).transform(map.displayProjection, map.getProjectionObject());
	    map.setCenter(lonLat, zoom);
    }
}

function moveendEvent(event){
    // alert("drag"+map.getCenter().lat+"lon"+map.getCenter().lon)
    var lonLat = map.getCenter().transform(map.getProjectionObject(), map.displayProjection);
    document.getElementById("input_lat").value = lonLat.lat;
    document.getElementById("input_lon").value = lonLat.lon;    
}

function updateCrosshair(evt) {
    crosshairControl.draw();
}

function calculateIconOffset(size) {
    return new OpenLayers.Pixel(-(size.w/2), -(size.h/2));
}

OpenLayers.Control.SituareCrosshair = OpenLayers.Class(OpenLayers.Control, {
    element: null,
    displayProjection: null,
    imageDiv: null,
    initialize: function(options){
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },
    destroy: function(){
//        if (this.map) {
//            this.map.events.unregister('mousemove', this, this.redraw);
//        }
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },
    draw: function(){
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        
        var currentMapSize = this.map.getCurrentSize();
        var position = new OpenLayers.Pixel(
                currentMapSize.w / 2 - CROSSHAIR_IMG_RADIUS, 
                currentMapSize.h / 2 - CROSSHAIR_IMG_RADIUS);
        if (!this.element) {            
            this.div = OpenLayers.Util.createAlphaImageDiv(null, position, new OpenLayers.Size(2*CROSSHAIR_IMG_RADIUS, 2*CROSSHAIR_IMG_RADIUS), CROSSHAIR_IMG_ADDRESS);
            this.element = this.div;
        }
        else {
            this.div.style.left = position.x + "px";
            this.div.style.top = position.y + "px";
        }
        this.redraw();
        return this.div;
    },
    redraw: function(evt){
        
    },
    CLASS_NAME: "OpenLayers.Control.SituareCrosshair"
});


/**
 * OpenStreetMap layer showing the position of Facebook friends via markers(profile photo), 
 * and poping up a ballon with additional info about the clicked friend.
 */
OpenLayers.Layer.SituareFriends = OpenLayers.Class(OpenLayers.Layer.Markers, {
    features: null,         // holds all the marker features
    selectedFeature: null,  // holds the selected marker feature
    markerSize: new OpenLayers.Size(16, 16),
    initialize: function(name, options){
        OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
        this.features = new Array();
        OpenLayers.Popup.FramedCloud.prototype.panIntoView = function(){};
    },
    destroy: function(){
        OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments);
        this.clearFeatures();
        this.features = null;
    },
    /**
     * Removes all the popups from the map.
     */
    removePopups: function() {
        for (var i = 0, len = this.map.popups.length; i < len; i++) {
            this.map.removePopup(this.map.popups[i]);
        }
    },
    /**
     * Event function - called when a marker is clicked.
     * 
     * @param {Object} evt event
     */
    markerClick: function(evt){
        // check is the same marker was clicked
        // if yes, then unselect the selected one,
        // if no, then set selected the clicked one
        var sameMarkerClicked = (this == this.layer.selectedFeature);
        this.layer.selectedFeature = (!sameMarkerClicked) ? this : null;
        // if none of the markers is selected then remove all the popups
        if (this.layer.selectedFeature==null) {
            this.layer.removePopups();
        }
        else {  // if any marker is selected, then open up the related popup balloon
            // create a popup object and add it the to the map
            this.layer.map.addPopup(
                new OpenLayers.Popup.FramedCloud(
                    this.id + "_popup",             // popup ID
                    this.lonlat,                    // popup position (lon, lat)
                    null,                           // content size
                    this.data.popupContentHTML,     // HTML text shown in the popup bubble
                    null,                           // anchor
                    false)                          // close button
            );                
        } 
        OpenLayers.Event.stop(evt);
    },
    /**
     * Event function, which closes the shown popups (only 1 is currently allowed), 
     * and unselects the currently selected feature.
     * 
     * @param {Object} evt
     */
    closePopups: function(evt) {
       this.removePopups();
       this.selectedFeature = null;       
    },
    selectNextPopup: function(ascending) {
        if (ascending==undefined) {
            ascending = true;
        }
        var currentFeature = this.selectedFeature;
        this.closePopups();
        var nextFeature = undefined;
        
        if (ascending) {
            for (var i = 0; i < this.features.length; i++) {
                if (currentFeature === this.features[i]) {
                    var nextFeatureIndex = (i + 1) % this.features.length;
                    nextFeature = this.features[nextFeatureIndex];
                    break;
                }
            }
        }
        else {
            for (var i = this.features.length-1; i >= 0 ; i--) {
                if (currentFeature === this.features[i]) {
                    var nextFeatureIndex = (this.features.length + i - 1) % this.features.length;
                    nextFeature = this.features[nextFeatureIndex];
                    break;
                }
            }
        }
        
        if (nextFeature) {
            var userLonLat = this.map.getCenter().clone();
            userLonLat = userLonLat.transform(this.map.getProjectionObject(), this.map.displayProjection);
            this.showMeAndMyFriendFeature(userLonLat.lon, userLonLat.lat, nextFeature);
        }
        
//        if (nextFeature) {
//            this.map.addPopup(
//                new OpenLayers.Popup.FramedCloud(
//                    nextFeature.id + "_popup",              // popup ID
//                    nextFeature.lonlat,                     // popup position (lon, lat)
//                    null,                                   // content size
//                    nextFeature.data.popupContentHTML,      // HTML text shown in the popup bubble
//                    null,                                   // anchor
//                    false)                                  // close button
//            );
//            
//            this.selectedFeature = nextFeature;  
//        }
        
    },
    openPopupByFeature: function(feature) {
        this.closePopups();
        this.map.addPopup(
                new OpenLayers.Popup.FramedCloud(
                    feature.id + "_popup",              // popup ID
                    feature.lonlat,                     // popup position (lon, lat)
                    null,                               // content size
                    feature.data.popupContentHTML,      // HTML text shown in the popup bubble
                    null,                               // anchor
                    false)                              // close button
            );
            
        this.selectedFeature = feature; 
    },
    openPopupByUID: function(uid) {
        var friendFeature = this.getFeatureByUID(fid);
        
        if (friendFeature!=null) {
            this.openPopupByFeature(friendFeature);
        }
    },
    getFeatureByUID: function(uid) {
       if (uid==undefined) {
           return null;
       }
       
       for (var i = this.features.length - 1; i >= 0; i--) {
           if (this.features[i].data.uid == uid) {
               return this.features[i];
           }
       }
       
       return null;
    },
    getZoomLevel: function(userLonLat, friendLonLat) {
    	var boundsCenter = new OpenLayers.LonLat(0, 0);
        var zoomLevel = this.map.baseLayer.resolutions.length-1;
        for (var i=this.map.baseLayer.resolutions.length-1; i>=0; i--) {        
            var resolution = this.map.baseLayer.resolutions[i];        
            var bounds = this.map.calculateBounds(boundsCenter, resolution);
            bounds = bounds.transform(this.map.getProjectionObject(), this.map.displayProjection);
            bounds.left += userLonLat.lon;
            bounds.right += userLonLat.lon;
            bounds.top += userLonLat.lat;
            bounds.bottom += userLonLat.lat;
            
            var cont = bounds.contains(friendLonLat.lon, friendLonLat.lat);         
            if (cont) {
                zoomLevel = (i==0 ? 0 : i-1);
                break;
            }       
        }
        
        return zoomLevel;
    },
    showMeAndMyFriendFeature: function(userLon, userLat, friendFeature) {
    	if (userLon==null) {
    		userLon = document.getElementById("input_lon").value;
    	}
    	if (userLat==null) {
    		userLat = document.getElementById("input_lat").value;
    	}
    	
        if (userLon==null || userLat==null || friendFeature==null) {
            return;
        }

        var userLonLat = new OpenLayers.LonLat(userLon, userLat);
        var friendLonLat = friendFeature.lonlat.clone().transform(this.map.getProjectionObject(), this.map.displayProjection);
                
        var zoom = this.getZoomLevel(userLonLat, friendLonLat);   
        map.zoomTo(zoom);
        
        this.openPopupByFeature(friendFeature);
    },
    /**
     * 
     * @param {Object} userLon
     * @param {Object} userLat
     * @param {Object} fid      Can be uid of the friend (typeof number) or OpenLayers.Feature object
     */
    showMeAndMyFriend: function(userLon, userLat, fid) {
        if (typeof fid == "number") {
            var friendFeature = this.getFeatureByUID(fid);    
        }
        else {
            var friendFeature = fid;
        }        
        
        this.showMeAndMyFriendFeature(userLon, userLat, friendFeature);
    },
    calculateIconOffset: function(size) {
        return new OpenLayers.Pixel(-(size.w/2), -(size.h/2));
    },
    /**
     * Cretes a Friend marker.
     * The data paramete array should have the following elements:
     * <li>longitude - the longitude part of the marker position
     * <li>latitude - the latitude part of the marker position
     * <li>imgurl - source of the marker image (url of the friend's profile photo)
     * 
     * @param {Object} data 
     */
    createFriendMarker: function(data) {
        var lonLat = new OpenLayers.LonLat(data.longitude, data.latitude).transform(this.map.displayProjection, this.map.getProjectionObject());
        data.icon = new OpenLayers.Icon(data.imgurl, this.markerSize, null, this.calculateIconOffset);
        
        var markerFeature = new OpenLayers.Feature(this, lonLat, data);
        this.features.push(markerFeature);
        var marker = markerFeature.createMarker();
        marker.events.register('click', markerFeature, this.markerClick);
        this.map.events.register('click', this, this.closePopups);
        this.addMarker(marker);
    },    
    clearFeatures: function(){
        if (this.features != null) {
            while (this.features.length > 0) {
                var feature = this.features[0];
                OpenLayers.Util.removeItem(this.features, feature);
                feature.destroy();
            }
        }
    },
    CLASS_NAME: "OpenLayers.Layer.SituareFriends"    
});


//map move 

function map_move(){
	
	alert("Map move")
	var lonLat = new OpenLayers.LonLat( document.getElementById("input_lon").value , document.getElementById("input_lat").value ).transform(map.displayProjection, map.getProjectionObject());
    map.setCenter(lonLat, map.zoom);
	
	
}
